package com.yuyou.hxyy.gateway;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yuyou.hxyy.service.api.bean.ResBoolSimpleInfo;
import com.yuyou.hxyy.service.api.bean.ReturnCode;
import com.yuyou.hxyy.service.api.bean.ReturnResult;
import com.yuyou.hxyy.service.api.exception.BusinessException;
import com.yuyou.hxyy.service.api.exception.CheckException;
import com.yuyou.hxyy.service.api.exception.ResBoolSimpleInfoException;
import com.yuyou.hxyy.service.api.util.LogUtil;

@ControllerAdvice
public class ExceptionHandle {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());  
	
	/**
	 * BindException bean校验请求参数统一处理
	 * @param ex
	 * @return
	 */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ReturnResult<List<String>> bindException(BindException ex) {
    	BindingResult  result=ex.getBindingResult();
    	List<String> messList=new ArrayList<String>();
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
            	messList.add(error.getDefaultMessage());
            }
        }
    	LogUtil.error(logger, "请求参数有误ParamsError:", ex);
        return ReturnResult.fail("请求参数有误:"+messList,messList,ReturnCode.code._3002.getCode(),ReturnCode.code._3002.getMessage()+":"+messList);
    }
	
    /**
     * ValidationException method校验请求参数统一处理
     * @param exception
     * @return
     */
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public ReturnResult<List<String>> handle(ValidationException exception) {
    	List<String> messList=new ArrayList<String>();
            ConstraintViolationException exs = (ConstraintViolationException) exception;

            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
            	messList.add(item.getMessage());
            }
        	LogUtil.error(logger, "请求参数有误ParamsError:", exs);
            return ReturnResult.fail("请求参数有误:"+messList,messList,ReturnCode.code._3002.getCode(),ReturnCode.code._3002.getMessage()+":"+messList);   
    }
    
    /**
     * @RequestParam 参数校验统一处理
     * @param ex
     * @return
     */
    @ExceptionHandler(ServletRequestBindingException.class)
    @ResponseBody
    public ReturnResult<List<String>> servletRequestBindingException(ServletRequestBindingException ex) {
    	LogUtil.error(logger, "请求参数有误ParamsError:", ex);
        return ReturnResult.fail("请求参数有误:",ex.getMessage(),ReturnCode.code._3002.getCode(),ReturnCode.code._3002.getMessage());
    }
        
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ReturnResult sethodArgumentNotValidException(HttpServletRequest httpServletRequest,MethodArgumentNotValidException ex) throws Exception {
    	
    	BindingResult  result=ex.getBindingResult();
    	List<String> messList=new ArrayList<String>();
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
            	messList.add(error.getDefaultMessage());
            }
        }    	
        String mess=messList.stream().collect(Collectors.joining(","));
    	LogUtil.error(logger, "请求参数有误ParamsError:"+mess, ex);
        return ReturnResult.fail(mess,null,ReturnCode.code._2001.getCode(),ReturnCode.code._2001.getMessage());
    }
    
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public ReturnResult businessException(Exception e){    	 
    	LogUtil.error(logger, "自定义异常:", e);
        return ReturnResult.fail(e.getMessage(),null,ReturnCode.code._2001.getCode(),ReturnCode.code._2001.getMessage());
    }
    
    @ExceptionHandler(value = ResBoolSimpleInfoException.class)
    @ResponseBody
    public ResBoolSimpleInfo<String> ResBoolSimpleInfoException(Exception e){    	 
    	LogUtil.error(logger, "自定义异常:", e);
    	ResBoolSimpleInfo<String> res=new ResBoolSimpleInfo<String>();
    	res.setSuccess(false);
    	res.setMessage(e.getMessage());
        return res;
    }
      
    @ExceptionHandler(value = CheckException.class)
    public void defCheckException(CheckException e) throws CheckException{    	
    	LogUtil.error(logger, "CheckException:", e);
    	throw new CheckException("CheckException:",e);
    }
    
    /**
     * 判断错误是否是已定义的已知错误，不是则由未知错误代替，同时记录在log中
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ReturnResult allException(Exception e){    
    	LogUtil.error(logger, "未捕捉异常UnknownError:", e);
        return ReturnResult.fail("服务器异常,请联系管理员",null,ReturnCode.code._2001.getCode(),ReturnCode.code._2001.getMessage());
    }
}
